<?php
Junction_FileCabinet::package("Junction_Utils");
Junction_FileCabinet::package("Junction_Utils_Xml");
Junction_FileCabinet::package("Junction_Utils_Resource");
Junction_FileCabinet::package("Junction_Utils_Reflection");

/**
 * Build instances of Junction_Core_Mapping based on a schema file
 * 
 * @package junction.core
 */
class Junction_Core_Builder {
	/**
	 * Xml parser
	 *
	 * @var Junction_Utils_Xml_Parser
	 */
	private $_xml;
	
	public function __construct() {
		$this->_xml = new Junction_Utils_Xml_Parser();
		$resources = new Junction_Utils_Resource_Manager($this);
		foreach ($resources as $key) {
			$this->setHandler($key, $resources->getString($key));
		}
	}
	
	/**
	 * Build and return a new Junction_Core_Mapping
	 * 
	 * <p>This implementation assumes that the id tag will be the first 
	 * tag under class.
	 * 
	 * TODO evaluate whether we want to relax this restriction and how
	 * 
	 * @param Junction XML schema file
	 * @return Junction_Core_Mapping
	 */
	public function build($schema) {
		$stack = $this->_xml->parseFile($schema);
		$class = $stack->pop();
		while ($stack->size() > 1) { 
			$class->bindProperty($stack->pop());
		}
		$class->bindKey($stack->pop());
		return $class;
	}
	
	/**
	 * Instantiate the specified handler and assign it to the parser
	 *
	 * @param String $tag
	 * @param String $handler valid handler classname
	 */
	private function setHandler($tag, $handler) {
		try {
			$handle = Junction_Utils_Reflection_Facade::getInstance($handler, array());
			$this->_xml->setHandler($tag, $handle);
		} catch (Junction_Utils_Reflection_Exception $e) {
			throw new Junction_Core_Exception($e->getMessage());
		}
	}
}
?>